package ws

import (
	"kugo/log"
	"kugo/utils"
	"reflect"

	"github.com/gorilla/websocket"
)

type SocketSingleton struct {
	bind   interface{}
	conn   *websocket.Conn
	pool   *socketPool
	closed bool
}

func newSocketSingleton(conn *websocket.Conn, pool *socketPool) *SocketSingleton {
	return &SocketSingleton{
		conn:   conn,
		pool:   pool,
		closed: false,
	}
}

func (s *SocketSingleton) SetBind(data interface{}) {
	s.bind = data
}

func (s *SocketSingleton) GetBind() interface{} {
	return s.bind
}

func (s *SocketSingleton) SendData(cmd string, message interface{}) {
	data := buildPack(cmd, message)
	err := s.SendString(data)
	if err != nil {
		log.ErrLog("发送失败:%s", err.Error())
		panic(err)
	}
}

func (s *SocketSingleton) SendString(message interface{}) error {
	value := reflect.ValueOf(message)
	valueType := value.Type()
	var data string
	if valueType.Kind() != reflect.String {
		data = utils.Struct2JSON(message)
	} else {
		data = message.(string)
	}
	err := s.conn.WriteMessage(websocket.TextMessage, []byte(data))
	if err != nil {
		// logManager.ErrLog("发送失败 %s %s", s.bind.mark, message)
		if !s.closed {
			s.Close()
		}
	}
	if data != "pong" {
		log.Info("send[%d]: %s", s.bind.(int64), data)
	}
	return err
}

func (s *SocketSingleton) receive() (string, error) {
	_, message, err := s.conn.ReadMessage()
	if err != nil {
		return "", err
	}
	return string(message), nil
}

func (s *SocketSingleton) Close() {
	if !s.closed {
		err := s.conn.Close()
		s.pool.removeConnection(s.bind.(int64))
		s.closed = true
		if err != nil {
			return
		}
	}
}

func (s *SocketSingleton) handleConnection() {
	//连接成功
	defer s.Close() // 确保连接在函数结束时关闭
	for {
		// 读取消息
		message, err := s.receive()
		if err != nil {
			// 发生错误，可能是连接关闭了
			break
		}
		if message == "ping" {
			s.SendString("pong")
			// log.Info("ID[%d]心跳: %s", s.bind.(int64), message)
			continue
		}
		// 处理接收到的消息
		log.Info("recv[%d]: %s", s.bind.(int64), message)
		var data pack
		data, err = analyzeCmd(message)
		if err != nil {
			break
		}
		eventMgr.Emit(data.Cmd, s, data.Data)
	}
}
